{% extends "../platformmgr/base.html" %}

{% load admin_utils %}

{% block main_content %}
<div id="evaluation-list" class="p10">
    <div class="mb15" v-if="collect_task">
        <h5>最新采集任务:</h5>
        <span>开始时间：$[collect_task.start_at]</span>
        <span class="ml25">耗时：$[collect_task.duration]</span>
        <span class="ml25">总 / 成 / 败：$[collect_task.total_count] / $[collect_task.succeed_count] / $[collect_task.failed_count]</span>
        <span class="ml25">状态：$[collect_task.status]</span>
        <hr/>
    </div>
    <div class="mb15" style="display: flex; justify-content: space-between">
        <bk-input
            placeholder="输入应用 Code 或名称，按 Enter 进行模糊搜索"
            :clearable="true"
            :right-icon="'bk-icon icon-search'"
            v-model="filterKey"
            @enter="handleSearch"
            style="width: 40%"
        ></bk-input>
        <bk-button class="ml15 mr15" @click="handleExport">
            导出数据
        </bk-button>
    </div>
    <div class="mb15">
        <h5>按问题类型过滤：</h5>
        <bk-radio-group v-model="issueType" @change="handleSearch">
            <bk-radio value="" class="m5">
                <i class="bk-icon">不过滤</i>
            </bk-radio>
            <bk-radio value="none" class="m5">
                <i class="bk-icon">正常</i>
            </bk-radio>
            <bk-radio value="ownerless" class="m5">
                <i class="bk-icon">无主</i>
            </bk-radio>
            <bk-radio value="idle" class="m5">
                <i class="bk-icon">闲置</i>
            </bk-radio>
            <bk-radio value="unvisited" class="m5">
                <i class="bk-icon">无用户访问</i>
            </bk-radio>
            <bk-radio value="maintainless" class="m5">
                <i class="bk-icon">缺少维护</i>
            </bk-radio>
            <bk-radio value="undeploy" class="m5">
                <i class="bk-icon">未部署/已下线</i>
            </bk-radio>
            <bk-radio value="misconfigured" class="m5">
                <i class="bk-icon">配置不当</i>
            </bk-radio>
        </bk-radio-group>
    </div>
    <bk-table :data="data" @sort-change="handleSortChange">
        <bk-table-column label="应用 Code">
            <template slot-scope="props">
                <a class="cell" @click="handleView(props.row)">$[props.row.app_code]</a>
            </template>
        </bk-table-column>
        <bk-table-column label="应用名称" prop="app_name"></bk-table-column>
        <bk-table-column label="评估结果" width="100">
            <template slot-scope="props">
                <bk-tag
                    theme="success"
                    v-if="props.row.issue_type == 'none'"
                > ✔ </bk-tag>
                <bk-tag
                    theme="danger"
                    v-else
                    v-bk-tooltips="genIssuesTooltipsConfig(props.row)"
                > ✘ </bk-tag>
            </template>
        </bk-table-column>
        <bk-table-column label="内存 Requests" prop="mem_requests" sortable="custom"></bk-table-column>
        <bk-table-column label="内存 Limits" prop="mem_limits" sortable="custom"></bk-table-column>
        <bk-table-column label="内存使用率（7d)" prop="mem_usage_avg" sortable="custom"></bk-table-column>
        <bk-table-column label="CPU Requests" prop="cpu_requests" sortable="custom"></bk-table-column>
        <bk-table-column label="CPU Limits" prop="cpu_limits" sortable="custom"></bk-table-column>
        <bk-table-column label="CPU 使用率（7d)" prop="cpu_usage_avg" sortable="custom"></bk-table-column>
        <bk-table-column label="PV (30d)" prop="pv" sortable="custom"></bk-table-column>
        <bk-table-column label="UV (30d)" prop="uv" sortable="custom"></bk-table-column>
        <bk-table-column label="最新操作人" prop="latest_operator"></bk-table-column>
        <bk-table-column label="最新操作时间" prop="latest_operated_at"></bk-table-column>
        <bk-table-column label="采集时间" prop="collected_at"></bk-table-column>
    </bk-table>
    <pagination
        class="mt15"
        :current.sync="pagination.curPage"
        :limit="pagination.limit"
        :count="pagination.count"
        :align="'right'"
    ></pagination>

    <bk-dialog
        v-model="dialog.visible"
        header-position="left"
        width="1100"
        :mask-close="true"
        :show-footer="false"
    >
        <div slot="header">应用资源使用详情</div>
        <bk-container :col="3">
            <bk-row>
                <bk-col><label class="m10">应用 Code:</label> $[dialog.form.app_code]</bk-col>
                <bk-col><label class="m10">应用名称:</label> $[dialog.form.app_name]</bk-col>
            </bk-row>
            <bk-row>
                <bk-col><label class="m10">内存请求:</label> $[dialog.form.mem_requests]</bk-col>
                <bk-col><label class="m10">内存限制:</label> $[dialog.form.mem_limits]</bk-col>
                <bk-col><label class="m10">平均使用率（7d）:</label> $[dialog.form.mem_usage_avg]</bk-col>
            </bk-row>
            <bk-row>
                <bk-col><label class="m10">CPU 请求:</label> $[dialog.form.cpu_requests]</bk-col>
                <bk-col><label class="m10">CPU 限制:</label> $[dialog.form.cpu_limits]</bk-col>
                <bk-col><label class="m10">平均使用率（7d）:</label> $[dialog.form.cpu_usage_avg]</bk-col>
            </bk-row>
            <bk-row>
                <bk-col><label class="m10">PV（30d）:</label> $[dialog.form.pv]</bk-col>
                <bk-col><label class="m10">UV（30d）:</label> $[dialog.form.uv]</bk-col>
                <bk-col><label class="m10">采集时间:</label> $[dialog.form.collected_at]</bk-col>
            </bk-row>
            <bk-row>
                <bk-col><label class="m10">最新操作人:</label> $[dialog.form.latest_operator || '--' ]</bk-col>
                <bk-col><label class="m10">操作时间:</label> $[dialog.form.latest_operated_at || '--' ]</bk-col>
                <bk-col><label class="m10">内容:</label> $[dialog.form.latest_operation || '--' ]</bk-col>
            </bk-row>
            <bk-row>
                <bk-col><label class="m10">最新部署人:</label> $[dialog.form.latest_deployer || '--' ]</bk-col>
                <bk-col><label class="m10">部署时间:</label> $[dialog.form.latest_deployed_at || '--' ]</bk-col>
                <bk-col>
                    <label class="m10">
                        <a :href="getAppOverviewUrl(dialog.form.app_code)" target="_blank">跳转到应用概览</a>
                    </label>
                </bk-col>
            </bk-row>
        </bk-container>
        <h4 class="mt20">模块进程</h4>
        <bk-collapse accordion>
            <bk-collapse-item v-for="(module, module_name) in dialog.form.res_summary.modules" :name="module_name">
                <!-- 如果该模块的某个环境有问题，则提示感叹号 -->
                $[ module_name ] <span v-if="hasEvaluateIssues(module_name)">❗</span>
                <div slot="content">
                    <bk-tab type="unborder-card">
                        <bk-tab-panel
                            v-for="(panel, index) in dialog.env_panels"
                            v-bind="panel"
                            :key="index">
                            <!-- 如果该环境有问题，则提示感叹号 -->
                            <template slot="label">
                                <span> $[panel.label] </span>
                                <i v-if="hasEvaluateIssues(module_name, panel.name)">❗</i>
                            </template>
                            <div v-if="hasEvaluateIssues(module_name, panel.name)">
                                <bk-alert type="error" :title="getEnvEvaluateIssues(module_name, panel.name)"></bk-alert>
                            </div>
                            <bk-container :col="3">
                                <bk-row>
                                    <bk-col><label class="m10">CPU 平均使用率（7d）:</label> $[ (getEnvResSummary(module_name, panel.name).cpu_usage_avg * 100).toFixed(2) ] %</bk-col>
                                    <bk-col><label class="m10">内存平均使用率（7d）:</label> $[ (getEnvResSummary(module_name, panel.name).mem_usage_avg * 100).toFixed(2) ] %</bk-col>
                                </bk-row>
                                <bk-row>
                                    <bk-col><label class="m10">PV（30d）:</label> $[ getEnvVisitSummary(module_name, panel.name).pv ]</bk-col>
                                    <bk-col><label class="m10">UV（30d）:</label> $[ getEnvVisitSummary(module_name, panel.name).uv ]</bk-col>
                                    <bk-col><label class="m10">最近部署时间:</label> $[ getEnvDeploySummary(module_name, panel.name).latest_deployed_at ]</bk-col>
                                </bk-row>
                            </bk-container>
                            <hr />
                            <h5>进程详情：</h5>
                            <bk-container :col="5" v-for="proc in getEnvProcs(module, panel.name)" v-if="proc.quota">
                                <bk-row>
                                    <bk-col><label class="m10">进程名称:</label><b> $[proc.name] </b></bk-col>
                                    <bk-col><label class="m10">副本数量:</label> $[proc.replicas]</bk-col>
                                    <bk-col><label class="m10">资源套餐:</label> $[proc.current_plan]</bk-col>
                                </bk-row>
                                <bk-row>
                                    <bk-col><label class="m10">内存请求:</label> $[proc.quota.requests.memory] Mi</bk-col>
                                    <bk-col><label class="m10">内存限制:</label> $[proc.quota.limits.memory] Mi</bk-col>
                                    <bk-col><label class="m10">采样数量:</label> $[proc.memory.cnt]</bk-col>
                                </bk-row>
                                <bk-row>
                                    <bk-col><label class="m10">平均值:</label> $[proc.memory.avg] Mi</bk-col>
                                    <bk-col><label class="m10">中位值:</label> $[proc.memory.med] Mi</bk-col>
                                    <bk-col><label class="m10">最大值:</label> $[proc.memory.max] Mi</bk-col>
                                    <bk-col><label class="m10">p75:</label> $[proc.memory.p75] Mi</bk-col>
                                    <bk-col><label class="m10">p95:</label> $[proc.memory.p90] Mi</bk-col>
                                </bk-row>
                                <bk-row>
                                    <bk-col><label class="m10">CPU 请求:</label> $[proc.quota.requests.cpu] m</bk-col>
                                    <bk-col><label class="m10">CPU 限制:</label> $[proc.quota.limits.cpu] m</bk-col>
                                    <bk-col><label class="m10">采样数量:</label> $[proc.cpu.cnt]</bk-col>
                                </bk-row>
                                <bk-row>
                                    <bk-col><label class="m10">平均值:</label> $[proc.cpu.avg] m</bk-col>
                                    <bk-col><label class="m10">中位值:</label> $[proc.cpu.med] m</bk-col>
                                    <bk-col><label class="m10">最大值:</label> $[proc.cpu.max] m</bk-col>
                                    <bk-col><label class="m10">p75:</label> $[proc.cpu.p75] m</bk-col>
                                    <bk-col><label class="m10">p95:</label> $[proc.cpu.p90] m</bk-col>
                                </bk-row>
                                <hr>
                            </bk-container>
                        </bk-tab-panel>
                    </bk-tab>
                </div>
            </bk-collapse-item>
        </bk-collapse>
    </bk-dialog>
</div>

{% endblock %}

{% block main_script %}
<script>
const collect_task = {{ latest_collect_task | default:"null" | safe }}
const pagination = {{ pagination | to_json }}
const data = {{ usage_report_list | to_json }}
const SEARCH_PARAM = "search_term"
const ISSUE_TYPE_PARAM = "issue_type"

document.addEventListener('DOMContentLoaded', () => {
    new Vue({
        el: "#evaluation-list",
        delimiters: ['$[', ']'],
        data: function () {
            let prefix = window.location.href
            let filterKey = undefined
            let issueType = undefined

            if (prefix.indexOf("?") > 0) {
                let query = querystring.parse(prefix.substr(prefix.indexOf("?") + 1))
                filterKey = query[SEARCH_PARAM]
                issueType = query[ISSUE_TYPE_PARAM]
            }
            return {
                data,
                pagination,
                collect_task,
                appOverviewUrl: '{% url "admin.applications.detail.overview" "app_code" %}',
                dataExportUrl: '{% url "admin.applications.operation_evaluation.export" %}',
                SEARCH_PARAM,
                ISSUE_TYPE_PARAM,
                filterKey,
                issueType,
                dialog: {
                    visible: false,
                    form: {
                        res_summary: {
                            modules: []
                        },
                    },
                    env_panels: [
                        {"name": "prod", "label": "生产环境"},
                        {"name": "stag", "label": "预发布环境"}
                    ]
                }
            }
        },
        methods: {
            getAppOverviewUrl(app_code) {
                return this.appOverviewUrl.replace("app_code", app_code)
            },
            handleView(row) {
                this.dialog.form = row
                this.dialog.visible = true
            },
            getEnvResSummary(module_name, env_name) {
                return this.dialog.form.res_summary.modules[module_name].envs[env_name]
            },
            getEnvVisitSummary(module_name, env_name) {
                return this.dialog.form.visit_summary.modules[module_name].envs[env_name]
            },
            getEnvDeploySummary(module_name, env_name) {
                return this.dialog.form.deploy_summary.modules[module_name].envs[env_name]
            },
            getEnvEvaluateResult(module_name, env_name) {
                return this.dialog.form.evaluate_result.modules[module_name].envs[env_name]
            },
            hasEvaluateIssues(module_name, env_name) {
                let stag_env_has_issues = this.getEnvEvaluateResult(module_name, "stag").issue_type !== "none"
                let prod_env_has_issues = this.getEnvEvaluateResult(module_name, "prod").issue_type !== "none"

                if (env_name === "stag") {
                    return stag_env_has_issues
                } else if (env_name === "prod") {
                    return prod_env_has_issues
                }
                return stag_env_has_issues || prod_env_has_issues
            },
            getEnvEvaluateIssues(module_name, env_name) {
                let result = this.getEnvEvaluateResult(module_name, env_name)
                if (result.issue_type === "none") {
                    return ""
                }
                issue_type_display = {
                    "ownerless": "无主",
                    "idle": "闲置",
                    "unvisited": "无用户访问",
                    "maintainless": "缺少维护",
                    "undeploy": "未部署/已下线",
                    "misconfigured": "配置不当"
                }[result.issue_type]

                return `${issue_type_display}：${result.issues.join(", ")}`
            },
            getEnvProcs(module, tab_name) {
                return module.envs[tab_name].procs
            },
            handleSortChange({column, prop, order}) {
                if (!prop) {
                    return
                }
                let query = {
                    order_by: (order === 'ascending' ? prop : '-' + prop), offset:0
                }
                this.handleQueryChange(query)
            },
            handleSearch() {
                let query = {
                    [this.SEARCH_PARAM]: this.filterKey,
                    [this.ISSUE_TYPE_PARAM]: this.issueType,
                    offset:0
                }
                this.handleQueryChange(query)
            },
            handleQueryChange(query) {
                let prefix = window.location.href

                if (prefix.indexOf("?") > 0) {
                    query = {...querystring.parse(prefix.substr(prefix.indexOf("?") + 1)), ...query}
                    prefix = prefix.substr(0, prefix.indexOf("?"))
                }
                query = querystring.stringify(query)
                window.location.href = `${prefix}?${query}`
            },
            handleExport() {
                url = this.dataExportUrl
                if (this.issueType) {
                    url += "?issue_type=" + this.issueType
                }
                open(url)
            },
            genIssuesTooltipsConfig(row) {
                return {
                    content: row.issues.join('<br>'),
                    allowHTML: true
                }
            }
        },
    })
})

</script>

{% endblock %}
